package me.zhyd.justauth;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;

import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.request.AuthAlipayRequest;
import me.zhyd.oauth.request.AuthAliyunARMRequest;
import me.zhyd.oauth.request.AuthBaiduRequest;
import me.zhyd.oauth.request.AuthBootRequest;
import me.zhyd.oauth.request.AuthCodingRequest;
import me.zhyd.oauth.request.AuthCsdnRequest;
import me.zhyd.oauth.request.AuthDingTalkRequest;
import me.zhyd.oauth.request.AuthDouyinRequest;
import me.zhyd.oauth.request.AuthElemeRequest;
import me.zhyd.oauth.request.AuthFacebookRequest;
import me.zhyd.oauth.request.AuthGiteeRequest;
import me.zhyd.oauth.request.AuthGithubRequest;
import me.zhyd.oauth.request.AuthGitlabRequest;
import me.zhyd.oauth.request.AuthGoogleRequest;
import me.zhyd.oauth.request.AuthHuaweiRequest;
import me.zhyd.oauth.request.AuthKujialeRequest;
import me.zhyd.oauth.request.AuthLinkedinRequest;
import me.zhyd.oauth.request.AuthMeituanRequest;
import me.zhyd.oauth.request.AuthMiRequest;
import me.zhyd.oauth.request.AuthMicrosoftRequest;
import me.zhyd.oauth.request.AuthOschinaRequest;
import me.zhyd.oauth.request.AuthPinterestRequest;
import me.zhyd.oauth.request.AuthQqRequest;
import me.zhyd.oauth.request.AuthRenrenRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.AuthStackOverflowRequest;
import me.zhyd.oauth.request.AuthTaobaoRequest;
import me.zhyd.oauth.request.AuthTeambitionRequest;
import me.zhyd.oauth.request.AuthTencentCloudRequest;
import me.zhyd.oauth.request.AuthToutiaoRequest;
import me.zhyd.oauth.request.AuthWeChatRequest;
import me.zhyd.oauth.request.AuthWeiboRequest;
import me.zhyd.oauth.utils.AuthStateUtils;

/**
 * @author yadong.zhang (yadong.zhang0415(a)gmail.com)
 * @version 1.0
 * @website https://www.zhyd.me
 * @date 2019/2/19 9:28
 * @since 1.8
 */
@Controller
@RequestMapping("/oauth")
public class RestAuthController {

	private static final String DEFAULT_CLIENT_ID = "123";
	private static final String DEFAULT_CLIENT_SECRET = "jdjdjddjdjudijjj";
	@Value("${server.serverUrl}")
	private String serverUrl;
	
	@Autowired
	private RestTemplate restTemplate;
    @RequestMapping("/render/{source}")
    @ResponseBody
    public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
        System.out.println("进入render：" + source);
        AuthRequest authRequest = getAuthRequest(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        System.out.println(authorizeUrl);
        response.sendRedirect(authorizeUrl);
    }

    /**
     * oauth平台中配置的授权回调地址，以本项目为例，在创建github授权应用时的回调地址应为：http://127.0.0.1:8443/oauth/callback/github
     */
    @RequestMapping("/callback/{source}")
    public String login(@PathVariable("source") String source, Model model,AuthCallback callback) {
        System.out.println("进入callback：" + source + " callback params：" + JSONObject.toJSONString(callback));
        AuthRequest authRequest = getAuthRequest(source);
        AuthResponse response = authRequest.login(callback);
        System.out.println(JSONObject.toJSONString(response));
        model.addAttribute("source", source);
		model.addAttribute("wxMpUser", response.getData());
		return "oauth";
    }

    @RequestMapping("/revoke/{source}/{token}")
    @ResponseBody
    public Object revokeAuth(@PathVariable("source") String source, @PathVariable("token") String token) throws IOException {
        AuthRequest authRequest = getAuthRequest(source);
        return authRequest.revoke(AuthToken.builder().accessToken(token).build());
    }

    @RequestMapping("/refresh/{source}")
    @ResponseBody
    public Object refreshAuth(@PathVariable("source") String source, String token){
        AuthRequest authRequest = getAuthRequest(source);
        return authRequest.refresh(AuthToken.builder().refreshToken(token).build());
    }

    /**
     * 根据具体的授权来源，获取授权请求工具类
     *
     * @param source
     * @return
     */
    private AuthRequest getAuthRequest(String source) {
        AuthRequest authRequest = null;
        switch (source) {
            case "dingtalk":
                authRequest = new AuthDingTalkRequest(AuthConfig.builder()
                        .clientId("dingoavdtykn7s73v4mr5c")
                        .clientSecret("qvpTT4-7Ik_88yEivyz04vOvuFEjfFSIQXtuc84_WsX2KeD3ve1MfurzmRq-e88p")
                        .redirectUri(serverUrl+"/oauth/callback/dingtalk")
                        .build());
                break;
            case "baidu":
                authRequest = new AuthBaiduRequest(AuthConfig.builder()
                        .clientId("9FUmjPmoHlGQNnm3XL0RAEio")
                        .clientSecret("Em1oki36Bt1kGXSg6MotU4wc9wgXhKO0")
                        .redirectUri(serverUrl+"/oauth/callback/baidu")
                        .build());
                break;
            case "github":
                authRequest = new AuthGithubRequest(AuthConfig.builder()
                        .clientId("Iv1.9eecfa80b0a35af5")
                        .clientSecret("11e8442f11b831a3c2ed8db24b11c8adba724acd")
                        .redirectUri(serverUrl+"/oauth/callback/github")
                        .build());
                break;
            case "gitee":
                authRequest = new AuthGiteeRequest(AuthConfig.builder()
                        .clientId("2051dd43daf9d174528ff048b138b1ae7e675cd7c22060e675dad3336e98fd22")
                        .clientSecret("8e14035c5dd901b24f4f85909e4e27132fcc2dc8a0f5a71d6ad49a5d89af8c96")
                        .redirectUri(serverUrl+"/oauth/callback/gitee")
                        .build());
                break;
            case "weibo":
                authRequest = new AuthWeiboRequest(AuthConfig.builder()
                        .clientId("1516755492")
                        .clientSecret("55986ef52d0dcd961bc03295536c931c")
                        .redirectUri(serverUrl+"/oauth/callback/weibo")
                        .build());
                break;
            case "coding":
                authRequest = new AuthCodingRequest(AuthConfig.builder()
                        .clientId("3e889b3d131e334d0c59353635b46bfe")
                        .clientSecret("0d8111e92b473ed17aafd5eed3e49697ddc79837")
                        .redirectUri(serverUrl+"/oauth/callback/tencentCloud")
                        .build());
                break;
            case "tencentCloud":
                authRequest = new AuthTencentCloudRequest(AuthConfig.builder()
                        .clientId("72890406ffa6ef5d4c1243226c8b8035")
                        .clientSecret("7642011b6f142e1a938f006e64aa7dc491948a75")
                        .redirectUri(serverUrl+"/oauth/callback/tencentCloud")
                        .build());
                break;
            case "oschina":
                authRequest = new AuthOschinaRequest(AuthConfig.builder()
                        .clientId("HjTd1HPywN4u7ZMYYKdF")
                        .clientSecret("GpNV6NgMg5Jnmh8L9KR5u00DO55WtPvc")
                        .redirectUri(serverUrl+"/oauth/callback/oschina")
                        .build());
                break;
            case "alipay":
                // 支付宝在创建回调地址时，不允许使用localhost或者127.0.0.1，所以这儿的回调地址使用的局域网内的ip
                authRequest = new AuthAlipayRequest(AuthConfig.builder()
                        .clientId("2016080700186744")
                        .clientSecret("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZvaUVgA6RoqkZF7fc5EK5CJUkYu8O84Sozz3B6Tvsq5mRoNQAFdJTaw/Qxm8WtHg6cg1VjtOXjGAAVy/m79DUKEthHgSs2hhntWac2WB34j2Z3U2AKNkk6MWkSub0I8TmLzsiz4j8vxVpbxkWUKPvFdWCODZzJ18YJms0AVWJ7wOFwuZPkiBlsa/fDFSXVuEF5xG4p2fbPvxog0h/mjR8kxzX9J6TUsBr+7xPLbEw4vhZ5UOxZ7YDClZWNyH/iRofNIQ7xR9jovpJDFkPI1WbLFzkBbSRC15fHyQHcnp54T0gWmhJHa3r4TRDtkNBTEujeGyy4+scA4OVX3Et3mwdAgMBAAECggEAQHndaxfqhD9ghYqB7Jy6Mtmbmsf3FCEiyJ0pfFJxdD8/R2jYoDSGob9rwZYG7tG+/lvopbIhoRQZCuuFxmdbAC7p9g/dzBQnWg8kurEbmQuD5CyAnTgEYUtR4CYdl9QMdrDmLyI0hDMrKq2SKt6k8dcJVPR4OXEQm5M5MHVCx3aUJK6sIp766vBejMl6LNcitz7LIXLe51Gs9nhD5b8CNrDIhG+VXzFDu79eJvO3FPBseARLs56xzKvZqnnQ1/JtnhzAc17qhq4jjuHlKlITR4LCvxF+cDXSyDmipMvZr6BubV4QElLluEi8H/+EfSft9+nvdIhv4C1nGiIQfkwSjQKBgQDSgC/mXLEYhjTfvYGmBAHo8MKeazyCpCJ2HiXxOH33fddVNgObQ1w+u42cToSNZnaz1HJpEOdI9opH3kcGQ4LHwdih+yze6/9XA1jeK99uutXopNUKJCi/d9Co+C2tHtUSXLkhVzTJQ+FGxeZmxgt8RJvXfTJy5ls0hhHMiwiZzwKBgQC6+LaLXEu100Ff7lnNMDBguUgCJs9wRirDaKIwF8uRj6veiLogVl/cITIm6STGmwvcuFWLgPz2O921FjDGDj0Ew2bLdZuKapMVk1lf0Zpz7xmtPeltHObqJJlntchs8LJ9XTdTB/mtSoccGiAuoE0Q+yUgo3Y1gU3309vT0XwSUwKBgGewEOguHGXyJbVYSbaXHsG5ZoRWWlYXt4nrS9FIfHQenqUwmBIw2g1koVqvKofkQvBN45VxaBv+pRrFmMKzGoZ/K9COQwoDwaEA2xOFFOgcTCXum6oFKbU2taelqAowt8/1sJOFu1CwiRUtglJ5l0q9GO7KksEaSy7SI45XpgLtAoGBAJ/YlE+ul3eaZXC7WIDoquN2Y86bGYuWIWcwZECTh1EpsDkvUVjmH0wWAUds2SkGUuzflxsOKrXk1pXDo+0fLSGOYKqfIFwE4zx13dniW5a0GpKWtKK5K92PbqtQqUohuacd83eEAPwbFEl9OHhESb6zx7kQprX1lw/CS1Ta6qTLAoGABYqII9WFlnQ38CDmMt9BTlqlf7Ftj6ZtHO7mhH0XBRkvlMUUgqlu6WKezd7EMHZvr5KEh4tkkHozq/N7OkAjzUERJRBPm6HaocbfAmFSvBEAuE+bTczmLH6cdJX3nLYIjnCVG507VTqDucPXOgX/8kBzBPBROLmPd2vCdZwkd5U=")
                        .alipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuQm5GBcgZtj1G6KhXwXY7rKzMwrm9kcBJFURq7xtb5nsaLasfl6vfKtzTDtnfIKOZayTVfqJKS1hrgAIYDfddZOJHMYAwte80D4kd1IkVc4B8PxHELs76rxaVR+fz69BzIzuyySJcY85ceHVDzdlQzDzHgdWAvkMpqt0HFuWUUlvAeK8wF+PXiZAwzmd8vtqRuJ08amG2gEEIuhgXlBD9MxFKMGgHaaIAaunHnWyWLrqtJispr/mlFx0zXa8aSMhLU/xoHspMTm/gpwHAmSt7ebyj4IkC04SkfMAq5RzQtuf86V6zULAj/zr98+YieOSk2tj1vl/KxtpvyQnpYimPwIDAQAB")
                        .redirectUri(serverUrl+"/oauth/callback/alipay")
                        .build());
                break;
            case "qq":
                authRequest = new AuthQqRequest(AuthConfig.builder()
                        .clientId("1106168786")
                        .clientSecret("4ZKaLdWIWYGkjCIX")
                        .redirectUri(serverUrl+"/oauth/callback/qq")
                        .build());
                break;
            case "wechat":
                authRequest = new AuthWeChatRequest(AuthConfig.builder()
                        .clientId("wx0985b6dbaeeff28c")
                        .clientSecret("d3ba2d045ffc578abd0e9d23f8c93404")
                        .redirectUri(serverUrl+"/oauth/callback/wechat")
                        .build());
                break;
            case "csdn":
                authRequest = new AuthCsdnRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/csdn")
                        .build());
                break;
            case "taobao":
                authRequest = new AuthTaobaoRequest(AuthConfig.builder()
                        .clientId("28124456")
                        .clientSecret("61e6ea3a94b951a9007619cf4b93f771")
                        .redirectUri(serverUrl+"/oauth/callback/taobao")
                        .build());
                break;
            case "google":
                authRequest = new AuthGoogleRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/google")
                        .build());
                break;
            case "facebook":
                authRequest = new AuthFacebookRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/facebook")
                        .build());
                break;
            case "douyin":
                authRequest = new AuthDouyinRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/douyin")
                        .build());
                break;
            case "linkedin":
                authRequest = new AuthLinkedinRequest(AuthConfig.builder()
                        .clientId("81zya6jjcsgkrr")
                        .clientSecret("QONeV3krkpghoU2y")
                        .redirectUri(serverUrl+"/oauth/callback/linkedin")
                        .build());
                break;
            case "microsoft":
                authRequest = new AuthMicrosoftRequest(AuthConfig.builder()
                        .clientId("81zya6jjcsgkrr")
                        .clientSecret("QONeV3krkpghoU2y")
                        .redirectUri(serverUrl+"/oauth/callback/microsoft")
                        .build());
                break;
            case "mi":
                authRequest = new AuthMiRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/mi")
                        .build());
                break;
            case "toutiao":
                authRequest = new AuthToutiaoRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/toutiao")
                        .build());
                break;
            case "teambition":
                authRequest = new AuthTeambitionRequest(AuthConfig.builder()
                        .clientId("5dc912096b44ad0001efdd50")
                        .clientSecret("VZ5ZTmaVbsiC6bxsF6xTBU8Rzeuunbdy")
                        .redirectUri(serverUrl+"/oauth/callback/teambition")
                        .build());
                break;
            case "pinterest":
                authRequest = new AuthPinterestRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/pinterest")
                        .build());
                break;
            case "renren":
                authRequest = new AuthRenrenRequest(AuthConfig.builder()
                        .clientId("b4766743220a4f9da33b3b5c47ca1e6a")
                        .clientSecret("de43819489d4466c8e3acb52586f3dee")
                        .redirectUri(serverUrl+"/oauth/callback/renren")
                        .build(),restTemplate);
                break;
            case "stackoverflow":
                authRequest = new AuthStackOverflowRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/login_success")
                        .stackOverflowKey("")
                        .build());
                break;
            case "huawei":
                authRequest = new AuthHuaweiRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/huawei")
                        .build());
                break;
            case "wechatEnterprise":
                authRequest = new AuthHuaweiRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/wechatEnterprise")
                        .agentId("")
                        .build());
                break;
            case "kujiale":
                authRequest = new AuthKujialeRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/kujiale")
                        .build());
                break;
            case "gitlab":
                authRequest = new AuthGitlabRequest(AuthConfig.builder()
                        .clientId("512a4b3b5f6fc5174b86e277a9ebb86ca8c5328aaaa966adfc9ee7e41594bb47")
                        .clientSecret("740e099c0fe2c0f0d1b79535d489286e0b34f20caf3b7426c144b408188e8b2f")
                        .redirectUri(serverUrl+"/oauth/callback/gitlab")
                        .build());
                break;
            case "meituan":
                authRequest = new AuthMeituanRequest(AuthConfig.builder()
                        .clientId("3515734595601047")
                        .clientSecret("daec3f965955461781fa01643a004de7")
                        .redirectUri(serverUrl+"/oauth/callback/meituan")
                        .build());
                break;
            case "eleme":
                authRequest = new AuthElemeRequest(AuthConfig.builder()
                        .clientId(DEFAULT_CLIENT_ID)
                        .clientSecret(DEFAULT_CLIENT_SECRET)
                        .redirectUri(serverUrl+"/oauth/callback/eleme")
                        .build());
                break;
            case "aliyunArm":
                authRequest = new AuthAliyunARMRequest(AuthConfig.builder()
                        .clientId("4074444473614869695")
                        .clientSecret("c5af7dc9-f60e-4359-824b-34441d6955a3")
                        .redirectUri(serverUrl+"/oauth/callback/aliyunArm")
                        .build());
                break;
                //完全自定义的oauth
            case "boot":
                authRequest = new AuthBootRequest(AuthConfig.builder()
                        .clientId("4074444473614869695")
                        .clientSecret("OaH1heR2E4eGnBr87Br8FgY/Hauph1tqvVWiH4atxtegY/Hauph")
                        .redirectUri(serverUrl+"/oauth/callback/boot")
                        .build());
                break;
                  
            default:
                break;
        }
        if (null == authRequest) {
            throw new AuthException("未获取到有效的Auth配置");
        }
        return authRequest;
    }
}